home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
program
/
libkb100.zip
/
LIBKB-1.00
/
SRC
/
KBHANDLE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-23
|
12KB
|
567 lines
/* kbhandle.c -- MSDOS keyboard interrupt handler / Linux keyboard handler
* Copyright (C) 1995, 1996 Markus F.X.J. Oberhumer
* For conditions of distribution and use, see copyright notice in kb.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <limits.h>
#include <kb.h>
#include "_kb.h"
#if defined(KB_LOCK_ALL_START)
KB_LOCK_ALL_START(_libkb_kbhandle)
#endif
#if defined(__KB_MSDOS)
# define KB_ACKINT() KB_OUTP8(0x20, 0x20) /* ack. interrupt */
#else
# define KB_ACKINT() /* no interrupt */
#endif
/***********************************************************************
// globals
************************************************************************/
volatile unsigned char _kb_key[128]; /* the key flags */
volatile unsigned short _kb_shift = 0; /* shift state */
volatile int _kb_keys_pressed = 0; /* number of keys pressed */
volatile unsigned short _kb_last_key = 0; /* last key pressed */
int _kb_mode = 0; /* do we have a keyboard handler? */
unsigned long _kb_flags = 0; /* flags from kb_install() */
kb_handler_callback_t kb_handler_callback = NULL;
/***********************************************************************
// static variables
// These are not volatile because all access outside the
// interrupt handler uses KB_DISABLE().
************************************************************************/
static unsigned char _t_prefix = 0;
static char _emergency_done = 0; /* don't recurse here */
#define KEY_BUFFER_SIZE 256 /* store up to 256 keys for kb_keypress() */
static unsigned char _key_buffer[2*KEY_BUFFER_SIZE];
#define _key_buffer_start (&_key_buffer[0])
#define _key_buffer_end (&_key_buffer[HIGH(_key_buffer)])
static unsigned char *_key_buffer_head = _key_buffer_start;
static unsigned char *_key_buffer_tail = _key_buffer_start;
/* debugging and error reporting */
#if defined(KB_DEBUG)
static unsigned char _kb_port_buffer[128];
#define _kb_port_buffer_start (&_kb_port_buffer[0])
#define _kb_port_buffer_end (&_kb_port_buffer[sizeof(_kb_port_buffer)])
static unsigned char *_kb_port_buffer_head = _kb_port_buffer_start;
#endif
/* I've just (07 Jan 1996) taken a look at the Linux kernel source
* and come to the conclusion that reporting all unknown scan-codes
* as a bug is probably counterproductive.
* It seems that there exist lots of keyboards that produce lots
* of codes we are simply not interested in.
* I have removed all error reporting, the port values give us
* enough information if we want to add something new.
*/
/***********************************************************************
// reset all vars except _kb_flags
************************************************************************/
static void _kb_clear(void)
{
KB_DISABLE();
memset((void *)_kb_key,0,sizeof(_kb_key)); /* cast away volatile */
_kb_shift = 0;
_kb_keys_pressed = 0;
_kb_last_key = 0;
kb_handler_callback = 0;
_t_prefix = 0;
_key_buffer_head = _key_buffer_tail = _key_buffer_start;
KB_ENABLE();
}
/***********************************************************************
//
************************************************************************/
int kb_kbhit()
{
int c;
if (!_kb_mode)
return kb_os_kbhit();
kb_update();
KB_DISABLE();
c = (_key_buffer_head != _key_buffer_tail);
KB_ENABLE();
return c;
}
int kb_kbhit_i()
{
if (!_kb_mode)
return kb_os_kbhit();
kb_update();
return (_key_buffer_head != _key_buffer_tail);
}
void kb_clearkeys(void)
{
kb_update();
KB_DISABLE();
_key_buffer_tail = _key_buffer_head;
KB_ENABLE();
}
void kb_clearkeys_i(void)
{
kb_update();
_key_buffer_tail = _key_buffer_head;
}
/***********************************************************************
// basic keypress access.
// this function returns all relevant information:
// the scancode and the low bits of the shift status
// kb_getkey() and kb_inkey() sit on top of this function.
************************************************************************/
unsigned kb_keypress(void)
{
unsigned char scan, shift;
unsigned k;
if (!_kb_mode)
return 0;
kb_update();
KB_DISABLE();
if (_key_buffer_head == _key_buffer_tail)
{
KB_ENABLE();
return 0;
}
scan = *_key_buffer_tail++; /* get scan code */
shift = *_key_buffer_tail++; /* get shift code */
if (_key_buffer_tail >= _key_buffer_end)
_key_buffer_tail = _key_buffer_start;
KB_ENABLE();
k = scan | ((unsigned) shift << 8);
return k;
}
unsigned kb_keypress_i(void)
{
unsigned char scan, shift;
unsigned k;
if (!_kb_mode)
return 0;
kb_update();
if (_key_buffer_head == _key_buffer_tail)
return 0;
scan = *_key_buffer_tail++; /* get scan code */
shift = *_key_buffer_tail++; /* get shift code */
if (_key_buffer_tail >= _key_buffer_end)
_key_buffer_tail = _key_buffer_start;
k = scan | ((unsigned) shift << 8);
return k;
}
unsigned kb_keypeek(void)
{
unsigned char scan, shift;
unsigned k;
if (!_kb_mode)
return 0;
kb_update();
KB_DISABLE();
if (_key_buffer_head == _key_buffer_tail)
{
KB_ENABLE();
return 0;
}
scan = *_key_buffer_tail; /* get scan code */
shift = *(_key_buffer_tail+1); /* get shift code */
KB_ENABLE();
k = scan | ((unsigned) shift << 8);
return k;
}
unsigned kb_keypeek_i(void)
{
unsigned char scan, shift;
unsigned k;
if (!_kb_mode)
return 0;
kb_update();
if (_key_buffer_head == _key_buffer_tail)
return 0;
scan = *_key_buffer_tail; /* get scan code */
shift = *(_key_buffer_tail+1); /* get shift code */
k = scan | ((unsigned) shift << 8);
return k;
}
/***********************************************************************
// low level stuff
************************************************************************/
#if defined(__KB_MSDOS)
# include "_kbmsdos.h"
#elif defined(__KB_LINUX)
# include "_kblinux.h"
#endif
/***********************************************************************
// high level installation
************************************************************************/
int kb_init(void)
{
_kb_init_tables();
if (!_kb_mode)
_kb_clear();
return 0;
}
int kb_install(unsigned long flags)
{
if (_kb_mode)
return 0;
_kb_flags = flags;
_kb_flags &= 0xffff;
#if defined(KB_DEBUG)
fprintf(stderr,"kb_install 1: 0x%08lx\n", _kb_flags);
#endif
if (!(_kb_flags & KB_FLAG_NO_ATEXIT))
{
static unsigned char atexit_done = 0;
if (atexit_done)
_kb_flags |= KB_FLAG_ATEXIT_DONE;
else if (atexit(kb_remove) == 0)
{
_kb_flags |= KB_FLAG_ATEXIT_DONE;
atexit_done = 1;
}
else
_kb_flags |= KB_FLAG_ATEXIT_FAILED;
}
if (!(_kb_flags & KB_FLAG_NO_LOCK))
if (_kb_lock() == 0)
_kb_flags |= KB_FLAG_LOCK_DONE;
else
_kb_flags |= KB_FLAG_LOCK_FAILED;
/* link version information into executeable */
_kb_shift |= (kb_version_string[0] & kb_version_date[0] & kb_copyright[0]);
kb_init();
KB_DISABLE();
if (_kb_install() == 0)
_kb_mode = 1;
KB_ENABLE();
#if !defined(_KB_NO_SIGNALS)
/* install signals only if handler could be installed */
if (_kb_mode)
if (!(_kb_flags & KB_FLAG_NO_SIGNAL))
if (_kb_signal_install() == 0)
_kb_flags |= KB_FLAG_SIGNAL_DONE;
else
_kb_flags |= KB_FLAG_SIGNAL_FAILED;
#endif
#if !defined(_KB_NO_SIGNALS) && defined(SIGALRM)
if (_kb_mode)
if (_kb_flags & KB_FLAG_EMERGENCY_SIGALRM)
if (_kb_signal_alarm_install() != 0)
_kb_flags &= ~(KB_FLAG_EMERGENCY_SIGALRM); /* failed */
#else
_kb_flags &= ~(KB_FLAG_EMERGENCY_SIGALRM);
#endif
#if defined(KB_DEBUG)
fflush(stdout);
fprintf(stderr,"kb_install 2: 0x%08lx, %s\n", _kb_flags,
_kb_mode ? "ok" : "FAILED");
fflush(stderr);
#endif
return _kb_mode ? 0 : -1;
}
/***********************************************************************
// high level removal
************************************************************************/
typedef void (*kb_cleanup_t)(void);
static kb_cleanup_t
kb_cleanup_func1 = NULL,
kb_cleanup_func2 = NULL;
static kb_cleanup_t
kb_emergency_cleanup_func1 = NULL,
kb_emergency_cleanup_func2 = NULL;
void kb_set_cleanup( void (*before)(void), void (*after)(void) )
{
kb_cleanup_func1 = before;
kb_cleanup_func2 = after;
}